#if !defined(_PLUGIN_H)
#define _PLUGIN_H

#include <stack>

#include "tinyxml.h"

#include "alias.h"
#include "Command.h"
#include "SByte.h"
#include "SChar.h"
#include "SNumber.h"
#include "SString.h"
#include "SEnum.h"
#include "SVector.h"
#include "SStruct.h"
#include "SPluginException.h"
#include "DescriptorsRepository.h"
#include "INameResolutor.h"

CREATE_ALIAS( Plugin )
CREATE_MAP_ALIAS( Plugin )

/**
 * The plugin abstract base class.
 */
class DECLARATION_DLL Plugin
{
	/**
	* The command stack.
	*/
	stack<CommandSp> commandStack;

protected:

	/** The plugin name (must be equal to the plugin file name). */
	string pluginName;

	/**
	* Store the command name to call the right handler in the plugin implementation.
	*/
	string commandName;

	/**
	 * Reference to the descriptors repository.
	 */
	DescriptorsRepositorySp descriptorsRepository;

	/**
	 * Reference to a name resolutor.
	 */
	INameResolutorSp nameResolutor;

	/**
	* Reference to the command in execution inside the plugin.
	*/
	CommandSp cmd;

	/**
	 * Reference to inputs struct to get inputs in a command implementation.
	 */
	SStructSp inputs;

	/**
	 * Reference to outputs struct to set results in a command implementation.
	 */
	SStructSp outputs;

	/** Reference at the loaded plugins. */
	PluginSpMapSp plugins;

	/** Map useful to store common variables between commands. */
	SValueSpMapSp vars;

	/**
	 * Save in the command stack the status of the current command execution.
	 */
	void PushCommandStatus();

	/**
	 * Restore from the command stack the status of a command execution.
	 */
	void PopCommandStatus();

	/**
	 * Useful function to set an enum parameter from the numeric value.
	 */
	void SetEnumOutput( SEnumTypeDescriptorSp td, string name, unsigned long val, string alternative);

	/**
	* Load and parse the "<pluginName>.spd" xml file and create all the commands and the types.
	* The automatic loading of dependent plugins is implemented here.
	*/
	virtual void LoadScottPluginDescriptor(PluginSpMapSp plugins);

public:

	/**
	 *  Create a plugin with a specific name.
	 *  It's mandatory to call the InitializePlugin() function after the creation of the plugin.
	 */
	Plugin(string pluginName);

	/**
	 * Inizialize the plugin.		
	 */
	virtual void InitializePlugin(PluginSpMapSp plugins, INameResolutorSp nameResolutor);

	/**
	 * Get the name of the plugin.
	 */
	virtual string GetName()
	{
		return pluginName;
	}

	/**
	 * Execute a plugin command.
	 * Derived classes must override this method and call the base method.
	 */
	virtual void ExecuteCommand(CommandSp cmd);

private:

	/** 
	* Returns the value of an attribute with a specific name or
	* an empty string if the attribute is not present.
	*/
	string GetAttribute(TiXmlElement* elem, string attributeName);

};

/**
 * The Plugin entry pointer function.
 */
typedef Plugin* (*LoadPluginFunction)();

#endif // _PLUGIN_H
